package ace.module.stock.core.impl.manager.impl;

import ace.cmp.core.constants.CoreConstant;
import ace.cmp.util.AceEnumUtils;
import ace.cmp.util.AceStreamUtils;
import ace.module.common.core.impl.manager.impl.AbstractEntityOfAppManager;
import ace.module.stock.api.enums.WmsStockRecordActionTypeEnum;
import ace.module.stock.api.enums.WmsStockRecordReverseFlagEnum;
import ace.module.stock.api.model.dto.WmsStockRecordDto;
import ace.module.stock.api.model.input.WmsStockActionTypeRecordInput;
import ace.module.stock.core.impl.dao.entity.WmsStock;
import ace.module.stock.core.impl.dao.entity.WmsStockRecord;
import ace.module.stock.core.impl.dao.repository.WmsStockRecordRepository;
import ace.module.stock.core.impl.manager.WmsStockRecordManager;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

/**
 * 库存变更记录,保存1年 spring data jdbc querydsl rsql manager implement.
 *
 * @author Caspar
 */
@Slf4j
@AllArgsConstructor
@Component
public class WmsStockRecordManagerImpl
    extends AbstractEntityOfAppManager<WmsStockRecord, Long, WmsStockRecordDto>
    implements WmsStockRecordManager {

  private final WmsStockRecordRepository wmsStockRecordRepository;

  @Override
  public WmsStockRecord buildAddRecord(Long wmsAppId, Long stockId, Long quantity, String userSn) {
    return this.buildModifyRecord(wmsAppId, stockId, quantity, userSn, WmsStockRecordActionTypeEnum.ADD);
  }

  @Override
  public WmsStockRecord buildSubtractRecord(Long wmsAppId, Long stockId, Long quantity, String userSn) {
    return this.buildModifyRecord(wmsAppId, stockId, quantity, userSn, WmsStockRecordActionTypeEnum.SUBTRACT);
  }

  @Override
  public WmsStockRecord buildModifyRecord(Long wmsAppId, Long stockId, Long quantity, String batchSn, WmsStockRecordActionTypeEnum actionTypeEnum) {
    return this.buildModifyRecord(wmsAppId, stockId, quantity, batchSn, StringUtils.EMPTY, actionTypeEnum);
  }

  @Override
  public WmsStockRecord buildModifyRecord(Long wmsAppId, Long stockId, Long quantity, String batchSn, String remark, WmsStockRecordActionTypeEnum actionTypeEnum) {
    return WmsStockRecord.builder()
        .id(this.getNewId())
        .wmsAppId(wmsAppId)
        .stockId(stockId)
        .batchSn(batchSn)
        .reverseFlag(WmsStockRecordReverseFlagEnum.NONE.getCode())
        .reverseId(CoreConstant.ZERO_LONG)
        .actionType(actionTypeEnum.getCode())
        .quantity(quantity)
        .remark(remark)

        .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
        .createTime(System.currentTimeMillis())
        .updateTime(System.currentTimeMillis())
        .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
        .build();
  }

  @Override
  public List<WmsStockRecord> buildModifyRecord(Long wmsAppId, String batchSn, List<WmsStock> skuWmsStocks, List<WmsStockActionTypeRecordInput> wmsStockActionTypeRecordInputs) {
    return skuWmsStocks.stream()
        .map(wmsStockSku -> {
          WmsStockActionTypeRecordInput wmsStockActionTypeRecordInput = wmsStockActionTypeRecordInputs.stream()
              .filter(p -> wmsStockSku.getObjectId().equals(p.getObjectId()))
              .findFirst()
              .get();
          Long quantity = wmsStockActionTypeRecordInput.getQuantity();
          WmsStockRecordActionTypeEnum actionTypeEnum = AceEnumUtils.getEnum(WmsStockRecordActionTypeEnum.class, wmsStockActionTypeRecordInput.getActionType());
          return this.buildModifyRecord(wmsAppId, wmsStockSku.getId(), quantity, batchSn, actionTypeEnum);
        })
        .collect(Collectors.toList());
  }

  @Override
  public List<WmsStockRecord> buildAddOrSubtractReverseRecord(String reverseBatchSn, List<WmsStockRecord> preWmsStockRecords) {
    return AceStreamUtils.ofNullable(preWmsStockRecords)
        .map(preWmsStockRecord -> {
          return this.buildAddOrSubtractReverseRecord(reverseBatchSn, preWmsStockRecord);
        })
        .collect(Collectors.toList());
  }

  @Override
  public WmsStockRecord buildAddOrSubtractReverseRecord(String reverseBatchSn, WmsStockRecord preWmsStockRecord) {
    WmsStockRecordActionTypeEnum actionTypeEnum = null;
    if (WmsStockRecordActionTypeEnum.ADD.getCode().equals(preWmsStockRecord.getActionType())) {
      actionTypeEnum = WmsStockRecordActionTypeEnum.SUBTRACT;
    } else if (WmsStockRecordActionTypeEnum.SUBTRACT.getCode().equals(preWmsStockRecord.getActionType())) {
      actionTypeEnum = WmsStockRecordActionTypeEnum.ADD;
    } else {
      throw new IllegalArgumentException("还原操作仅支持增加或扣减操作");
    }

    return WmsStockRecord.builder()
        .id(this.getNewId())
        .wmsAppId(preWmsStockRecord.getWmsAppId())
        .stockId(preWmsStockRecord.getStockId())
        .batchSn(reverseBatchSn)
        .reverseFlag(WmsStockRecordReverseFlagEnum.NONE.getCode())
        .reverseId(preWmsStockRecord.getId())
        .actionType(actionTypeEnum.getCode())
        .quantity(preWmsStockRecord.getQuantity())
        .remark(StringUtils.EMPTY)

        .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
        .createTime(System.currentTimeMillis())
        .updateTime(System.currentTimeMillis())
        .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
        .build();
  }


  @Override
  public long countByWmsAppIdAndStockIdInAndBatchSnAndActionType(Long wmsAppId, List<Long> stockIds, String batchSn, WmsStockRecordActionTypeEnum actionTypeEnum) {
    return this.wmsStockRecordRepository.countByWmsAppIdAndStockIdInAndBatchSnAndActionTypeAndDeleteFlag(
        wmsAppId,
        stockIds,
        batchSn,
        actionTypeEnum.getCode(),
        CoreConstant.DELETE_FLAG_NOT
    );
  }

  @Override
  public List<WmsStockRecord> getByWmsAppIdAndBatchSnAndReverseFlagIsNoneAndActionTypeInAddSubtract(Long wmsAppId, String batchSn) {
    return this.wmsStockRecordRepository.findByWmsAppIdAndBatchSnAndReverseFlagAndActionTypeInAndDeleteFlag(
        wmsAppId,
        batchSn,
        WmsStockRecordReverseFlagEnum.NONE.getCode(),
        Arrays.asList(WmsStockRecordActionTypeEnum.ADD.getCode(), WmsStockRecordActionTypeEnum.SUBTRACT.getCode()),
        CoreConstant.DELETE_FLAG_NOT
    );
  }
}
